/**
 *
 */
package com.wedroid.r2d2.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import com.demo2do.core.persistence.GenericJdbcSupport;
import com.zaxxer.hikari.HikariDataSource;

/**
 * @author lute
 *
 */
@Configuration
public class DataAccessConfig {

    @Autowired
    @Qualifier("jdbc")
    private Properties jdbc;

    /**
     * Configure the data source
     * @return
     */
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setMaximumPoolSize(Integer.parseInt(jdbc.getProperty("pool.maximum_pool_size")));
        dataSource.setMaxLifetime(Long.parseLong(jdbc.getProperty("pool.maximum_lifetime")));
        dataSource.setAutoCommit(false);
        dataSource.setPoolName("r2d2Hikari");
        dataSource.setDataSourceClassName(jdbc.getProperty("datasource.class_name"));

        Properties dataSourceProperties = new Properties();
        dataSourceProperties.put("url", jdbc.getProperty("connection.url"));
        dataSourceProperties.put("user", jdbc.getProperty("connection.username"));
        dataSourceProperties.put("password", jdbc.getProperty("connection.password"));
        dataSourceProperties.put("prepStmtCacheSqlLimit", jdbc.getProperty("datasource.stmt.pre_cache_limit"));
        dataSourceProperties.put("prepStmtCacheSize", jdbc.getProperty("datasource.stmt.pre_cache_size"));
        dataSourceProperties.put("cachePrepStmts", jdbc.getProperty("datasource.stmt.pre_cache"));

        dataSource.setDataSourceProperties(dataSourceProperties);

        return dataSource;
    }

    /**
     * Configure generic JDBC support
     *
     * @param dataSource
     * @return
     */
    @Bean
    public GenericJdbcSupport genericJdbcSupport(DataSource dataSource) {
        GenericJdbcSupport genericJdbcSupport = new GenericJdbcSupport();
        genericJdbcSupport.setDataSource(dataSource);
        return genericJdbcSupport;
    }

//    /**
//     * @return
//     * @throws Exception
//     */
//    @Bean(autowire = Autowire.BY_TYPE)
//    public JdbcDaoInvocationHandler jdbcDaoInvocationHandler() throws Exception {
//        JdbcDaoInvocationHandler handler = new JdbcDaoInvocationHandler();
//        JdbcMySQLTemplateFactoryBean jdbcMySQLTemplateFactoryBean = new JdbcMySQLTemplateFactoryBean();
//        jdbcMySQLTemplateFactoryBean.setEntityPackages(new String[] { "com.wedroid.entity" });
//        handler.setSqlTemplate(jdbcMySQLTemplateFactoryBean.getObject());
//        return handler;
//    }
//
//    /**
//     * @return
//     * @throws Exception
//     */
//    @Bean
//    public JdbcDaoBeanPostProcessor jdbcDaoBeanPostProcessor() throws Exception {
//        JdbcDaoBeanPostProcessor processor = new JdbcDaoBeanPostProcessor();
//        processor.setInvocationHandler(jdbcDaoInvocationHandler());
//        processor.setDaoPackagesToScan("com.wedroid.r2d2.dao");
//        return processor;
//    }

    /**
     * @return
     */
    @Bean(autowire = Autowire.BY_NAME)
    public PlatformTransactionManager transactionManager() {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        return dataSourceTransactionManager;
    }

    /**
     * @param transactionManager
     * @return
     */
    @Bean
    public TransactionInterceptor transactionInterceptor(PlatformTransactionManager transactionManager) {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionManager(transactionManager);
        Properties transactionAttributes = new Properties();
        transactionAttributes.setProperty("count*", "PROPAGATION_REQUIRED,readOnly");
        transactionAttributes.setProperty("get*", "PROPAGATION_REQUIRED,readOnly");
        transactionAttributes.setProperty("list*", "PROPAGATION_REQUIRED,readOnly");
        transactionAttributes.setProperty("load*", "PROPAGATION_REQUIRED,readOnly");
        transactionAttributes.setProperty("*", "PROPAGATION_REQUIRED");
        interceptor.setTransactionAttributes(transactionAttributes);
        return interceptor;
    }

    /**
     * @return
     */
    @Bean
    public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
        BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
        beanNameAutoProxyCreator.setBeanNames("*Service");
        beanNameAutoProxyCreator.setProxyTargetClass(true);
        beanNameAutoProxyCreator.setInterceptorNames("transactionInterceptor");
        return beanNameAutoProxyCreator;
    }

}
